package com.yzh.openai.domain.weixin.service.message;

import com.alibaba.fastjson2.JSON;
import com.yzh.openai.domain.weixin.model.entity.MessageTextEntity;
import com.yzh.openai.domain.weixin.model.entity.UserBehaviorMessageEntity;
import com.yzh.openai.domain.weixin.repository.IWeiXinRepository;
import com.yzh.openai.types.utils.xml.XmlUtil;
import com.yzh.zhipu.model.ChatRequest;
import com.yzh.zhipu.model.ChatResponse;
import com.yzh.zhipu.model.args.Prompt;
import com.yzh.zhipu.model.vo.EventType;
import com.yzh.zhipu.model.vo.Model;
import com.yzh.zhipu.model.vo.Role;
import com.yzh.zhipu.session.ChatGlmSession;
import lombok.extern.slf4j.Slf4j;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import org.jetbrains.annotations.Nullable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.*;

@Slf4j
@Service
public class WeiXinBehaviorService extends AbstractWeiXinBehaviorService {
    @Resource
    private ThreadPoolExecutor executor;
    @Resource
    private ChatGlmSession ChatGlmSession;
    @Resource
    private IWeiXinRepository weiXinRepository;
    
    //缓存ai结果
    private static final Map<String, String> chatMap = new ConcurrentHashMap<>();
    //WX重试记录
    private static final Map<String, String> reTryMap = new ConcurrentHashMap<>();
    
    @Override
    protected String insertUserAccount(UserBehaviorMessageEntity userBehaviorMessageEntity) {
        try {
            //落库
            int res = weiXinRepository.insertUserAccount(userBehaviorMessageEntity.getOpenId());
            //落库失败
            if (res == 0) {
                log.error("用户落库失败,openId:{}", userBehaviorMessageEntity.getOpenId());
            }
        } catch (Exception e) {
            log.info("用户已存在！openId:{}", userBehaviorMessageEntity.getOpenId());
        }finally {
            //响应用户
            MessageTextEntity response = buildResponse(userBehaviorMessageEntity.getOpenId());
            String msg = "感谢您的关注！发送『666』获取网站验证码。本公众号已对接国内语言模型，可进行提问哦！(由于WX不可抗因素，问题响应需等待)";
            response.setContent(msg);
            return XmlUtil.beanToXml(response);
        }
    }
    
    /**
     * 创建验证码
     * @param userBehaviorMessageEntity
     * @return
     */
    public synchronized String createCode(UserBehaviorMessageEntity userBehaviorMessageEntity) {
        String code = weiXinRepository.genCode(userBehaviorMessageEntity.getOpenId());
        //反馈信息
        MessageTextEntity res = buildResponse(userBehaviorMessageEntity.getOpenId());
        res.setContent(String.format("您的访问码为:『%s』有效期3️⃣分钟！", code));
        return XmlUtil.beanToXml(res);
    }

    /**
     * 微信问答，对接的GLM接口
     * @param userBehaviorMessageEntity
     * @return
     */
    @Override
    public String QA(UserBehaviorMessageEntity userBehaviorMessageEntity) {
        String content = userBehaviorMessageEntity.getContent().trim();
        String openid = userBehaviorMessageEntity.getOpenId();
        //2.构建响应结果
        MessageTextEntity response = buildResponse(openid);
        String answer = chatMap.get(content);
        try {
            //获取Sync响应对象
            //3.判断问题再缓存中有无答案
            if (null != answer) {
                String result = buildReturnResponse(response, answer, openid);
                return result;
            }

            //4.判断是否重试

            if (null != reTryMap.get(content)) {
                log.info("接收微信公众号信息请求重试...");
                if (null != answer) {
                    return buildReturnResponse(response, answer, openid);
                } else {
                    return buildReturnResponse(response, "抱歉❗由于AI模型生成速度较慢😵💦，您需要稍等10秒再次回复相同问题得到答案【" + content + "】", openid);
                }
            }

            Future future = doChatTask(content);
            reTryMap.put(content, "unique");
            //等待异步结果
            log.info("Future 任务等待中...");
            future.get(30, TimeUnit.SECONDS);
            log.info("Future 任务执行完毕...");

            if (null != chatMap.get(content)) {
                return buildReturnResponse(response, chatMap.get(content), openid);
            } else {
                return buildReturnResponse(response, "抱歉❗由于AI模型生成速度较慢😵💦，您需要稍等10秒再次回复相同问题得到答案【" + content + "】", openid);
            }
        } catch (Exception e) {
            log.error("接收微信公众号信息请求{}失败\n{}", openid, JSON.toJSONString(userBehaviorMessageEntity), e);
            reTryMap.remove(content);
            return buildReturnResponse(response, "抱歉❗🌐网络出现波动~ 请稍后重试🔁", openid);
        }
    }
    
    @Async
    public Future doChatTask(String content) {
        return executor.submit(() -> {
            log.info("任务启动中...");

            ChatRequest request = new ChatRequest();
            request.setModel(Model.CHATGLM_TURBO);
            request.setPrompt(new ArrayList<Prompt>() {
                {
                    add(Prompt.builder().role(Role.user.getCode()).content(content).build());
                }
            });

            //等待消息响应后，调用者放行
            CountDownLatch countDownLatch = new CountDownLatch(1);
            //拼接数据
            StringBuilder sb = new StringBuilder();
            ChatGlmSession.completions(request, new EventSourceListener() {

                @Override
                public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String event, String data) {
                    ChatResponse chatResponse = JSON.parseObject(data, ChatResponse.class);
                    sb.append(chatResponse.getData());
                    if (EventType.finish.getCode().equals(event)) {
                        String result = sb.toString();
                        chatMap.put(content, result);
                        countDownLatch.countDown();
                        log.info("智普清言API调用已完成\n{}", result);
                    }
                }
            });
        });
    }
}
